package folexpr.compiler.visitors.c_negation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import folexpr.compiler.CompilerConstants;
import folexpr.compiler.visitors.VisitResult;

public class NegReductionVisitResultNew extends VisitResult
{	
	private Collection<String> andOrConnectedExprImages;
	String operator = null;
	private QuantificationTransformationHelper quantification;	
	
	// flags di stato
	// se tutti nulli, il result non contiene nemmeno un atomo quindi mi prendo solo la sua resultExpr 
	private Boolean negated = null;
	private Boolean quantified = null;
	private Boolean atomic = null;
	
	
	public NegReductionVisitResultNew()
	{
		super();

		this.andOrConnectedExprImages = new ArrayList<String>();
		this.operator = "";
		this.quantification = new QuantificationTransformationHelper();
	}
	
	//////////////////////////////////////////////////////////////////////////////////////////
	
	public void addResultString(String s) { this.resultExpr = this.resultExpr + s; }
	public String toString()
	{ 
		return "STRINGA="      + this.getResultExpr() + " " + 
		       "LISTA-ANDOR="  + this.dumpAndOrExprList() + " " + 
		       this.getQuantification().dump() + " " +
		       "OPERATORE="    + this.getOperator() + " " +
		       this.printFlags();
	}
	
	private String printFlags() {
		return "FLAGS=(N="+this.isNegated() +"||Q="+this.isQuantified() +"||A="+this.isAtomic()+")";
	}

	public String toStringLite() { return "STRINGA=" + this.getResultExpr(); }
	private String dumpAndOrExprList()
	{
		String result="[ ";
		boolean first=true;
		
		Iterator i = this.getAndOrConnectedExprImages().iterator();
		while (i.hasNext())
		{
			if (first)
			{
				result = result + (String)i.next();
				first=false;
			}
			else result = result + " , " + (String)i.next();
		}
		result = result + " ]" ;
		
		return result;
		
	}
	public boolean nullFlags() { return ((this.negated==null) && (this.quantified==null) && (this.atomic==null)); }
	
	public void mergeWithAnotherResult(NegReductionVisitResultNew newResult) 
	{
		if (newResult==null) return;
		
		this.addResultString(newResult.getResultExpr());
		
		if ( newResult.nullFlags() && !this.nullFlags()) { /* do nothing */ }
		if ( newResult.nullFlags() &&  this.nullFlags()) { /* do nothing */ }
		if (!newResult.nullFlags() &&  this.nullFlags())
		{
			this.setAndOrConnectedExprImages(newResult.getAndOrConnectedExprImages());
			this.setQuantification(newResult.getQuantification());
			this.setOperator(newResult.getOperator());
			this.setNegated(newResult.isNegated());
			this.setQuantified(newResult.isQuantified());
			this.setAtomic(newResult.isAtomic());
		}
		if (!this.nullFlags() && !newResult.nullFlags()) 
		{
			if (CompilerConstants.LOG_NEG_RED_VISITOR)
					System.out.println("@ @ @ @ @ WARNING: merging two not empty result objects: leaving unchenaged bur results may be incorrect... @ @ @ @ @");
			mergeQuantificationData(this,newResult);
			//operator...
			mergeAndOrData(this,newResult);
		}

	}
	
	private void mergeQuantificationData(NegReductionVisitResultNew thisResult , NegReductionVisitResultNew newResult)
	{
		if (thisResult.getQuantification().getQuantificator()==null && newResult.getQuantification().getQuantificator()!=null)
			thisResult.setQuantification(newResult.getQuantification());
		
		if (thisResult.getQuantification().getQuantificator()!=null && newResult.getQuantification().getQuantificator()!=null)
			if (CompilerConstants.LOG_NEG_RED_VISITOR)
				System.out.println("@ @ @ @ @ WARNING: merging two not empty quantification result objects: leaving unchanged but results may be incorrect... @ @ @ @ @");
			
	}
	private void mergeAndOrData(NegReductionVisitResultNew thisResult , NegReductionVisitResultNew newResult)
	{
		if ( thisResult.getAndOrConnectedExprImages().isEmpty() && !newResult.getAndOrConnectedExprImages().isEmpty())
			thisResult.setAndOrConnectedExprImages(newResult.getAndOrConnectedExprImages());
		
		if (!thisResult.getAndOrConnectedExprImages().isEmpty() && !newResult.getAndOrConnectedExprImages().isEmpty()) {
			if (CompilerConstants.LOG_NEG_RED_VISITOR)
				System.out.println("@ @ @ @ @ WARNING: merging two not empty andOrData result objects: result is theri union nut may be incorrect... @ @ @ @ @");
				//thisResult.getAndOrConnectedExprImages().addAll(newResult.getAndOrConnectedExprImages());
		}
	}

	
	///////////////////////////  GETTERs AND SETTERs  ////////////////////////////////////////

	public Collection<String> getAndOrConnectedExprImages() {return andOrConnectedExprImages;}
	public void setAndOrConnectedExprImages(Collection<String> andOrConnectedExprImages) {this.andOrConnectedExprImages = andOrConnectedExprImages;}
	public QuantificationTransformationHelper getQuantification() { return quantification; }
	public void setQuantification(QuantificationTransformationHelper quantification) { this.quantification = quantification; }

	public String getOperator() { return this.operator; }
	public void setOperator(String operator){ this.operator=operator; }
	
	public Boolean isNegated(){return this.negated;}
	public void setNegated(boolean negated){this.negated=negated;}
	public Boolean isQuantified(){return this.quantified;}
	public void setQuantified(boolean quantified){this.quantified=quantified;}
	public Boolean isAtomic(){return this.atomic;}
	public void setAtomic(boolean atomic){this.atomic=atomic;}
	
}



class QuantificationTransformationHelper
{
	String quantificator = null;
	String var = null;
	String theRest = null;
	
	public QuantificationTransformationHelper()
	{
		this.quantificator = null;
		this.var = null;
		this.theRest = null;
	}
	public QuantificationTransformationHelper(String quantificator,String operator,String var, String theRest)
	{
		this.quantificator = quantificator;
		this.var = var;
		this.theRest = theRest;
	}
	
	////////////////////////////////////////////////////////////////////////////////////////////
	
	public String dump(){ return "QUANTIFICATION=("+ quantificator + ";" + var + ";" + theRest + ")"; }
	
	////////////////////////////////////////////////////////////////////////////////////////////
	
	public String getQuantificator() { return quantificator; }
	public void setQuantificator(String quantificator) { this.quantificator = quantificator; }
	public String getTheRest() { return theRest; }
	public void setTheRest(String theRest) { this.theRest = theRest; }
	public String getVar() { return var; }
	public void setVar(String var) { this.var = var; }

}